package app

import (
	"context"
	"time"

	"code.byted.org/gopkg/logs/v2/log"

	"github.com/pkg/errors"

	"code.byted.org/bytertc/whiteboard_server/biz/api"
	"code.byted.org/bytertc/whiteboard_server/biz/pkg/biz_error"
	"code.byted.org/middleware/hertz/pkg/app"
	"code.byted.org/middleware/hertz_ext/v2/binding"
	"code.byted.org/middleware/hertz_ext/v2/middlewares/cors"
)

func wrapperMW(funcError handlerFuncError) app.HandlerFunc {
	return func(ctx context.Context, c *app.RequestContext) {
		err := funcError(ctx, c)
		if err != nil {
			handleError(ctx, c, err)
			c.Abort()
		}
		c.Next(ctx)
	}
}

func (w *Whiteboard) CORS() app.HandlerFunc {
	return cors.New(cors.Config{
		AllowAllOrigins:  true,
		AllowMethods:     []string{"POST", "GET", "OPTIONS"},                                                //允许的请求方式
		AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type", "Authorization", "xcluster"}, //允许带上的请求头
		AllowCredentials: false,                                                                             //是否附带cookies
		MaxAge:           12 * time.Hour,                                                                    //客户端缓存preflight请求最大时长（秒）
		ExposeHeaders:    []string{"X-Tt-Logid", "X-tt-Logid"},                                              //允许返回的响应头
	})
}

func (w *Whiteboard) CheckOnerToken(ctx context.Context, c *app.RequestContext) error {
	return w.checkToken(ctx, c, false)
}

func (w *Whiteboard) CheckByteToken(ctx context.Context, c *app.RequestContext) error {
	return w.checkToken(ctx, c, true)
}

func (w *Whiteboard) CheckWpsToken(ctx context.Context, c *app.RequestContext) error {
	c.Request.SetHeader("Authorization", string(c.GetHeader("X-WebOffice-Token")))
	err := w.checkToken(ctx, c, true)
	if err != nil {
		body, _ := c.Body()
		log.V1.CtxWarn(ctx, "body:%s,token:%s", string(body), c.GetHeader("X-WebOffice-Token"))
	}
	return err
}

func (w *Whiteboard) checkToken(ctx context.Context, c *app.RequestContext, isByte bool) error {
	headers := &api.Header{}
	err := binding.BindAndValidate(c, headers)
	if err != nil {
		return biz_error.InvalidParam.Wrap(err)
	}
	decodeAuthParams, err := w.tokenHelper.Check(ctx, headers.Token, isByte)
	if err != nil {
		return err
	}
	if decodeAuthParams == nil {
		return biz_error.InvalidParam.Wrap(errors.Errorf("token invalid decodeAuthParams is empty"))
	}
	if !isByte {
		query := &api.GetTokenQuery{}
		err := binding.BindAndValidate(c, query)
		if err != nil {
			return biz_error.InvalidParam.Wrap(err)
		}
		if query.AppID != decodeAuthParams.AppID {
			return biz_error.InvalidParam.Wrap(errors.Errorf("invalid token"))
		}
	}
	rawAuthParams := &api.AuthTokenKeyParams{}
	err = binding.BindAndValidate(c, rawAuthParams)
	if err != nil {
		return err
	}
	if rawAuthParams.AppID != "" && rawAuthParams.AppID != decodeAuthParams.AppID {
		return biz_error.InvalidParam.Wrap(errors.Errorf("invalid raw app_id"))
	}
	if rawAuthParams.RoomID != "" && rawAuthParams.RoomID != decodeAuthParams.RoomID {
		return biz_error.InvalidParam.Wrap(errors.Errorf("invalid raw room_id"))
	}
	if rawAuthParams.Operator != "" && rawAuthParams.Operator != decodeAuthParams.Operator {
		return biz_error.InvalidParam.Wrap(errors.Errorf("invalid raw operator"))
	}
	c.Request.SetHeader("X-WPS-APPID", decodeAuthParams.AppID)
	return nil
}
